import { ExtractionTask } from '../types';
import { EventEmitter } from 'events';
import * as fs from 'fs';
import * as path from 'path';
import { glob } from 'glob';
import { logger } from '../utils/logger';

interface FileScannerEvents {
  scanCompleted: (result: { totalFiles: number; files: string[] }) => void;
  scanError: (error: unknown) => void;
}

export class FileScanner extends EventEmitter {
  /**
   * 提取任务配置
   */
  private task: ExtractionTask;

  /**
   * 排除文件的匹配模式数组
   * 用于过滤不需要扫描的文件
   */
  private excludePatterns: string[];

  /**
   * 文件类型映射
   * 键为文件类型名称，值为对应的文件扩展名数组
   */
  private fileTypes: Map<string, string[]>;

  /**
   * Git 仓库路径
   */
  private repoPath: string;

  /**
   * 文件扫描器构造函数
   * @param task 提取任务配置对象
   */
  constructor(task: ExtractionTask) {
    super();
    this.task = task;
    // 标准化排除模式，确保格式一致性
    this.excludePatterns = this.normalizePatterns(task.excludePatterns || []);
    // 初始化支持的文件类型映射
    this.fileTypes = this.initializeFileTypes();
    // 设置 Git 仓库路径
    this.repoPath = task.gitConfig?.clonePath || '';
  }

  // 重写 on 方法以支持类型安全的事件监听
  on(
    event: 'scanCompleted',
    listener: (result: { totalFiles: number; files: string[] }) => void
  ): this;
  on(event: 'scanError', listener: (error: unknown) => void): this;
  on(event: string, listener: (...args: any[]) => void): this {
    return super.on(event, listener);
  }

  // 重写 emit 方法以支持类型安全的事件触发
  emit(event: 'scanCompleted', result: { totalFiles: number; files: string[] }): boolean;
  emit(event: 'scanError', error: unknown): boolean;
  emit(event: string, ...args: any[]): boolean {
    return super.emit(event, ...args);
  }

  /**
   * 扫描文件
   */
  public async scan(): Promise<string[]> {
    try {
      const files: string[] = [];

      // 扫描每个源路径
      for (const sourcePath of this.task.sourcePaths) {
        const sourceFiles = await this.scanDirectory(sourcePath);
        files.push(...sourceFiles);
      }

      // 触发扫描完成事件
      this.emit('scanCompleted', {
        totalFiles: files.length,
        files,
      });

      return files;
    } catch (error) {
      // 触发扫描错误事件
      this.emit('scanError', error);
      throw error;
    }
  }

  /**
   * 扫描目录
   * @param dirPath 目录路径
   */
  private async scanDirectory(dirPath: string): Promise<string[]> {
    const files: string[] = [];

    // 使用 Git 仓库路径作为基准路径
    const absolutePath = path.join(this.repoPath, dirPath);

    // 检查目录是否存在
    if (!fs.existsSync(absolutePath) || !fs.statSync(absolutePath).isDirectory()) {
      throw new Error(`无效的目录路径: ${dirPath} (解析为: ${absolutePath})`);
    }

    // 使用glob模式扫描文件
    const patterns = this.getGlobPatterns(absolutePath);
    // logger.info('开始扫描目录文件', {
    //   目录: dirPath,
    //   绝对路径: absolutePath,
    //   文件模式数量: patterns.length,
    //   排除模式: this.excludePatterns,
    //   任务ID: this.task.taskId,
    //   项目ID: this.task.projectId,
    // });
    for (const pattern of patterns) {
      const matches = await this.globFiles(pattern);
      files.push(...matches);
    }

    return files;
  }

  /**
   * 获取glob模式
   * @param dirPath 目录路径
   */
  private getGlobPatterns(dirPath: string): string[] {
    const patterns: string[] = [];

    logger.info('获取glob模式:', this.task.translationConfig);
    // 添加Android资源文件模式
    if (this.task.translationConfig.android) {
      patterns.push(path.join(dirPath, '**/*.{java,kt}'));
    }

    // 添加iOS本地化文件模式
    if (this.task.translationConfig.ios) {
      patterns.push(path.join(dirPath, '**/*.strings'));
    }

    // 添加Web翻译文件模式
    if (this.task.translationConfig.web) {
      patterns.push(path.join(dirPath, '**/*.{js,jsx,ts,tsx,vue}'));
    }

    return patterns;
  }

  /**
   * 使用glob扫描文件
   * @param pattern glob模式
   */
  private async globFiles(pattern: string): Promise<string[]> {
    try {
      return await glob(pattern, {
        ignore: this.excludePatterns,
        nodir: true,
        absolute: true,
      });
    } catch (error: unknown) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      throw new Error(`Failed to scan files with pattern ${pattern}: ${errorMessage}`);
    }
  }

  /**
   * 初始化文件类型映射
   */
  private initializeFileTypes(): Map<string, string[]> {
    const fileTypes = new Map<string, string[]>();

    // Android文件类型
    fileTypes.set('android', [
      'res/values/strings.xml', 
      'res/values-*/strings.xml',
      '**/*.java',  // Java 源文件
      '**/*.kt'     // Kotlin 源文件
    ]);

    // iOS文件类型
    fileTypes.set('ios', ['*.strings', '*.stringsdict']);

    // Web文件类型
    fileTypes.set('web', ['*.js', '*.jsx', '*.ts', '*.tsx', '*.vue']);

    return fileTypes;
  }

  /**
   * 规范化排除模式
   * @param patterns 排除模式列表
   */
  private normalizePatterns(patterns: string[]): string[] {
    return patterns.map(pattern => {
      // 确保模式以**开头
      if (!pattern.startsWith('**')) {
        pattern = `**/${pattern}`;
      }
      return pattern;
    });
  }

  /**
   * 检查文件是否应该被处理
   * @param filePath 文件路径
   */
  private shouldProcessFile(filePath: string): boolean {
    // 检查文件是否存在
    if (!fs.existsSync(filePath)) {
      return false;
    }

    // 检查文件类型
    const ext = path.extname(filePath).toLowerCase();
    const fileName = path.basename(filePath);

    // 检查Android文件
    if (this.task.translationConfig.android) {
      if (ext === '.xml' && fileName === 'strings.xml') {
        return true;
      }
      // 添加对 Java 和 Kotlin 文件的支持
      if (ext === '.java' || ext === '.kt') {
        return true;
      }
    }

    // 检查iOS文件
    if (this.task.translationConfig.ios) {
      if (ext === '.strings' || ext === '.stringsdict') {
        return true;
      }
    }

    // 检查Web文件
    if (this.task.translationConfig.web) {
      if (['.js', '.jsx', '.ts', '.tsx', '.vue'].includes(ext)) {
        return true;
      }
    }

    return false;
  }
}
